/**
 * ━━━━━━神兽出没━━━━━━
 * 　　　┏┓　　　┏┓
 * 　　┏┛┻━━━┛┻┓
 * 　　┃　　　　　　　┃
 * 　　┃　　　━　　　┃
 * 　　┃　┳┛　┗┳　┃
 * 　　┃　　　　　　　┃
 * 　　┃　　　┻　　　┃
 * 　　┃　　　　　　　┃
 * 　　┗━┓　　　┏━┛
 * 　　　　┃　　　┃神兽保佑, 永无BUG!
 * 　　　　┃　　　┃Code is far away from bug with the animal protecting
 * 　　　　┃　　　┗━━━┓
 * 　　　　┃　　　　　　　┣┓
 * 　　　　┃　　　　　　　┏┛
 * 　　　　┗┓┓┏━┳┓┏┛
 * 　　　　　┃┫┫　┃┫┫
 * 　　　　　┗┻┛　┗┻┛
 * ━━━━━━感觉萌萌哒━━━━━━
 */
package com.zkgengkun.config;

import com.zkgengkun.constant.SysConstants;
import com.zkgengkun.listener.AmqpListenerMap;
import com.zkgengkun.listener.AmqpListenerString;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * Amqp rabbitMQ
 *
 * @author gengshikun
 * @date 2017/1/3
 */
@Configuration
public class AmqpConfig {

    @Bean(name = "connectionFactory")
    @ConfigurationProperties(prefix = "spring.rabbitmq")
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setPublisherConfirms(true); //必须要设置
        return connectionFactory;
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    //必须是prototype类型
    public RabbitTemplate rabbitTemplate(@Qualifier("connectionFactory") ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        return template;
    }

    /**
     * 针对消费者配置
     * 1. 设置交换机类型
     * 2. 将队列绑定到交换机
     * <p>
     * <p>
     * FanoutExchange: 将消息分发到所有的绑定队列，无routingkey的概念
     * HeadersExchange ：通过添加属性key-value匹配
     * DirectExchange:按照routingkey分发到指定队列
     * TopicExchange:多关键字匹配
     */
    @Bean(name = "directExchange")
    public DirectExchange exchange() {
        DirectExchange directExchange = new DirectExchange(SysConstants.AMQP_DEFAULT_EXCHANGE);
        directExchange.setDelayed(Boolean.TRUE); // 支持延迟队列
        return directExchange;
    }

    /**
     * 声明队列
     *
     * @return
     */
    @Bean(name = "defaultQueue")
    public Queue defaultQueue() {
        return new Queue(SysConstants.AMQP_QUEUE_DEFAULT, true); //队列持久
    }

    @Bean(name = "mapQueue")
    public Queue mapQueue() {
        return new Queue(SysConstants.AMQP_QUEUE_MAP, true); //队列持久
    }

    /**
     * 绑定队列
     *
     * @return
     */
    @Bean
    public Binding defaultBinding(@Qualifier("defaultQueue") Queue defaultQueue,
                                  @Qualifier("directExchange") DirectExchange directExchange) {
        return BindingBuilder.bind(defaultQueue).to(directExchange).with(SysConstants.AMQP_ROUTINGKEY_DEFAULT);
    }

    @Bean
    public Binding mapBinding(@Qualifier("mapQueue") Queue mapQueue,
                              @Qualifier("directExchange") DirectExchange directExchange) {
        return BindingBuilder.bind(mapQueue).to(directExchange).with(SysConstants.AMQP_ROUTINGKEY_MAP);
    }

    @Bean
    public SimpleMessageListenerContainer stringMessageContainer(@Qualifier("connectionFactory") ConnectionFactory connectionFactory,
                                                                 @Qualifier("mapQueue") Queue mapQueue) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setQueues(mapQueue);
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
        container.setMessageListener(new AmqpListenerMap());
        return container;
    }

    @Bean
    public SimpleMessageListenerContainer mapMessageContainer(@Qualifier("connectionFactory") ConnectionFactory connectionFactory,
                                                              @Qualifier("defaultQueue") Queue defaultQueue) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setQueues(defaultQueue);
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
        container.setMessageListener(new AmqpListenerString());
        return container;
    }

}
